home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 7 / BBS in a Box - Macintosh - Volume VII (BBS in a Box) (January 1993).iso / Files / Tele / Pete Johnson / mehit 3.0.b15<source>.cpt / mehit.p < prev    next >
Text File  |  1991-07-10  |  38KB  |  1,372 lines

  1. program mehit;
  2.  
  3. {    Version information                                                    }
  4. {    2.01    runs correctly under MultiFinder with new HelloTabby unit                }
  5. {    2.03    fixes SFPutFile for message text list                                }
  6. {    2.04 won't delete last message, to keep high message mark intact                }
  7. {    2.05 moves messages in section 0 to section 255, where they can be deleted        }
  8. {    2.06 is a bug fix for 2.05                                            }
  9. {    2.07 can undelete public messages, stuffs messages, adds Log-O-Matic functions    }
  10.  
  11.  
  12. uses
  13.     Globals, Help, HelloTabby, mehitFile, Backup, Centerer, FileAndStuffIt, mehitDialogs;
  14.  
  15. const
  16.     Demo = false;    {    if true, amnesia on 1st & 16th, otherwise perfect memory    }
  17.     StrId = 256;        {    # of STR# resource            }
  18.     AppleID = 256;    {    # of Apple menu resource        }
  19.     FileID = 257;    {    # of File menu resource        }
  20.     EditID = 258;    {    # of Edit menu resource        }
  21.     GlobalID = 259;    {    # of Global menu resource    }
  22.     AlterSecsID = 1001;
  23.     SaveChangesID = 1002;
  24.     AboutId = 10000;    {    # of DLOG resource            }
  25.  
  26. var
  27.     OptionWindow: GrafPtr;            {    The main window            }
  28.     ScrollSect,                    {    Name+Scroll bar for list        }
  29.     Box,                        {    Spare rect variable            }
  30.     Databounds: Rect;                {    list dimensions            }
  31.     inCell,                        {    cell where new data goes        }
  32.     CSize: Point;                {    Size of a list cell            }
  33.     MessageList: ListHandle;        {    Handle to 1st list            }
  34.     TrueFalse,                    {    boolean variable            }
  35.     done: Boolean;                {    Are we done?                }
  36.     CellValue: str255;            {    What goes in a cell            }
  37.     TheEvent: eventrecord;            {    When we get the event        }
  38.     CommandState: integer;            {    State of Command key        }
  39.     AppleMenu, FileMenu, EditMenu, GlobalMenu: MenuHandle;
  40.     ControlResult, ItemType, ItemHit, RefNum: integer;
  41.     WhichControl: ControlHandle;
  42.     TotalLimits, AboutItem, ConfigItem, CharCode, KeyCode, Counter: integer;
  43.     Item: handle;
  44.     TempString, AlterTitle: STR255;
  45.     AlterDialog, HelpDialog, ConstructionDialog: DialogPtr;
  46.     thisButton: ControlHandle;
  47.     theCell, MouseLoc: Point;
  48.     theKeys: keyMap;
  49.     OldLevel, NewLevel: longint;
  50.     SFwhere: point;
  51.     SettingString, LimitString, AgeString, BackUpString, TheLaunch: Str255;
  52.     HBuffStr, TBuffStr: Str255;
  53.     launchVRefNum: integer;
  54.     beginning, WindowGone, NeedConfig: boolean;
  55.     DClickBox, CatBox: rect;
  56.  
  57. { ------------------------------------------------------ }
  58.  
  59. procedure Amnesia;
  60.  
  61.     var
  62.         Today: DateTimeRec;
  63.         AHandle: Handle;
  64.         OurResourceFile, ResourceCount: integer;
  65.  
  66.     begin
  67.         GetTime(Today);
  68.         if (Today.Day = 1) | (Today.Day = 16) then
  69.             begin
  70.                 for ResourceCount := 1 to 255 do
  71.                     begin
  72.                         AHandle := GetResource('STR ', 1000 + ResourceCount);
  73.                         if AHandle^ <> nil then
  74.                             RmveResource(AHandle);
  75.                     end;
  76.                 UpdateResFile(OurResourceFile);
  77.             end;
  78.     end;
  79.  
  80. { ------------------------------------------------------ }
  81.  
  82. function Launchit (pLnch: pLaunchStruct): OSErr;
  83.  
  84. inline
  85.     $205F, $A9F2, $3E80;
  86.  
  87. { ------------------------------------------------------ }
  88.  
  89. procedure Transfer;
  90.  
  91.     var
  92.         pMyLaunch: pLaunchStruct;
  93.         myLaunch: LaunchStruct;
  94.         MyPB: CInfoPBRec;
  95.  
  96.     begin
  97.         with MyPB do
  98.             begin
  99.                 ioNamePtr := @TheLaunch;
  100.                 ioVRefNum := launchVRefNum;
  101.                 ioFDirIndex := 0;
  102.                 ioDirID := 0;
  103.             end;    {    with    }
  104.         Err := PBGetCatInfo(@MyPB, false);
  105.  
  106.         pMyLaunch := @myLaunch;
  107.         with pMyLaunch^ do
  108.             begin
  109.                 pfName := @TheLaunch;
  110.                 param := 0;
  111.                 LC[0] := 'L';
  112.                 LC[1] := 'C';
  113.                 extBlockLen := 6;
  114.                 fFlags := myPB.ioFlFndrInfo.fdFlags;
  115.                 if MultiFinder then        {config multifinder}
  116.                     LaunchFlags := $C0000000        {    set BOTH high bits for a sublaunch    }
  117.                 else
  118.                     LaunchFlags := $00000000;        {    just launch, then quit    }
  119.             end;        {    with pMyLaunch^    }
  120.         Err := Launchit(pMyLaunch);
  121.     end;
  122.  
  123. { ------------------------------------------------------ }
  124.  
  125. procedure Strip (var TheString: STR255);
  126.  
  127. {    Strips leading and trailing spaces from string    }
  128.  
  129.     var
  130.         SpaceCount: integer;
  131.  
  132.     begin
  133.         while pos(' ', TheString) = 1 do
  134.             TheString := copy(TheString, 2, length(TheString) - 1);
  135.  
  136.         for SpaceCount := length(TheString) downto 1 do
  137.             if TheString[SpaceCount] = ' ' then
  138.                 TheString := copy(TheString, 1, length(TheString) - 1)
  139.             else
  140.                 leave;
  141.     end;
  142.  
  143. {-----------------------------------------------------------------    }
  144.  
  145. procedure Refresh;
  146.  
  147.     var
  148.         r: rect;
  149.         pad: str255;
  150.         lengthCount: integer;
  151.  
  152.     begin
  153.         SetPort(OptionWindow);
  154.         ForeColor(BlackColor);
  155.         r := MessageList^^.rView;        {    Get the rectangle…            }
  156.         InsetRect(r, -1, -1);        {    Stretch it a little bit…        }
  157.         FrameRect(r);                {    And draw it.                }
  158.         ForeColor(RedColor);
  159.         TextFont(Monaco);
  160.         TextSize(9);
  161.         GetDItem(OptionWindow, 1, ItemType, Item, Box);
  162.         SetDItem(OptionWindow, 1, ItemType, Item, Box);
  163.         GetDItem(OptionWindow, 2, ItemType, Item, Box);
  164.         SetDItem(OptionWindow, 2, ItemType, Item, Box);
  165.         GetDItem(OptionWindow, 4, ItemType, Item, Box);
  166.         SetDItem(OptionWindow, 4, ItemType, Item, Box);
  167.         GetDItem(OptionWindow, 11, ItemType, Item, Box);
  168.         pad := '';
  169.         for lengthCount := 1 to (9 - length(mehitVersion)) do
  170.             pad := concat(pad, ' ');
  171.         SetIText(Item, concat(pad, mehitVersion));
  172.         DrawDialog(OptionWindow);
  173.     end;
  174.  
  175. { ------------------------------------------------------ }
  176.  
  177. procedure FillList;
  178.  
  179.     var
  180.         Counter, FormatCount: integer;
  181.         Listing: STR255;
  182.  
  183.     begin
  184.         SetPort(OptionWindow);
  185.         ForeColor(BlackColor);
  186.         TextFont(Monaco);
  187.         TextSize(9);
  188.     {    Add items to the list.    }
  189.         inCell.h := 0;   {always in column 0}
  190.  
  191.         for Counter := 1 to SectionCount do
  192.             begin
  193.                 inCell.v := Counter - 1;    {    rows start at zero, but message sections from 1    }
  194.                 NumToString(Sections[Counter]^^.Number, Listing);
  195.                 for FormatCount := 1 to (3 - length(Listing)) do
  196.                     Listing := concat(' ', Listing);
  197.                 Listing := concat(Listing, '  ', Sections[Counter]^^.Name);
  198.                 for FormatCount := 1 to (30 - length(Listing)) do
  199.                     Listing := concat(Listing, '.');
  200.                 NumToString(Sections[Counter]^^.Limit, TempString);
  201.                 for FormatCount := 1 to (5 - length(TempString)) do
  202.                     TempString := concat(' ', TempString);
  203.                 Listing := concat(Listing, TempString);
  204.                 NumToString(Sections[Counter]^^.Age, TempString);
  205.                 for FormatCount := 1 to (5 - length(TempString)) do
  206.                     TempString := concat(' ', TempString);
  207.                 Listing := concat(Listing, TempString, '   ');
  208.                 if Sections[Counter]^^.Backup = true then
  209.                     Listing := concat(Listing, 'Y')
  210.                 else
  211.                     Listing := concat(Listing, 'N');
  212.                 LSetCell(Pointer(ord(@Listing) + 1), Length(Listing), inCell, MessageList);
  213.             end; {for}
  214.  
  215.     {    Scroll to the first item.                                }
  216.  
  217.         LAutoScroll(MessageList);
  218.  
  219.     {    Next lines add total sections to dialog                        }
  220.  
  221.         ForeColor(RedColor);
  222.         TextFont(Monaco);
  223.         TextSize(9);
  224.         GetDItem(OptionWindow, 1, ItemType, Item, Box);
  225.         NumToString(SectionCount, TempString);
  226.         SetIText(Item, TempString);
  227.  
  228.     {    Next lines add total limits to dialog                        }
  229.  
  230.         TotalLimits := 0;
  231.         for Counter := 1 to SectionCount do
  232.             if Sections[Counter]^^.Limit > 0 then
  233.                 TotalLimits := TotalLimits + Sections[Counter]^^.Limit;
  234.  
  235.         GetDItem(OptionWindow, 2, ItemType, Item, Box);
  236.         NumToString(TotalLimits, TempString);
  237.         SetIText(Item, TempString);
  238.  
  239.         GetDItem(OptionWindow, 4, ItemType, Item, Box);
  240.         NumToString(TotalLimits div SectionCount, TempString);
  241.         SetIText(Item, TempString);
  242.         ForeColor(BlackColor);
  243.  
  244.     end;
  245.  
  246. {-----------------------------------------------------------------    }
  247.  
  248. procedure SetUpLists;
  249.  
  250.     begin
  251.  
  252.     {    Set the list up using dimensions of User Item 3 in DLOG resource    }
  253.  
  254.         GetDItem(OptionWindow, 3, ItemType, Item, Box);
  255.  
  256.     {    One column x SectionCount means…                            }
  257.  
  258.         SetRect(DataBounds, 0, 0, 1, SectionCount);
  259.  
  260.     {    One cell is 14 pixels high by whatever wide…                    }
  261.  
  262.         cSize.v := 14;
  263.         cSize.h := Box.right - Box.left;
  264.  
  265.     {    Set up the 1st list.  Start drawing right away, and            }
  266.     {    put in a vertical scroll bar.                                }
  267.  
  268.         MessageList := LNew(Box, dataBounds, cSize, 0, OptionWindow, true, false, false, true);
  269.         Refresh;
  270.  
  271.         FillList;    {    fill list with message sections & settings    }
  272.  
  273.     {    You can only choose one item at a time.                        }
  274.  
  275.         MessageList^^.SelFlags := LOnlyOne;
  276.  
  277.     {    This sets up the rectangles for a MouseDown event.  It is the    }
  278.     {    view area of a list, plus a little extra for a scroll bar.        }
  279.  
  280.         ScrollSect := MessageList^^.rview;
  281.         ScrollSect.right := ScrollSect.right + 16;
  282.  
  283.     end;
  284.  
  285. {-----------------------------------------------------------------    }
  286.  
  287. procedure FillDialogItems (Str1: STR255; var OldLevel: longint);
  288.  
  289.     var
  290.         FormatCount: integer;
  291.  
  292.     begin
  293.  
  294.         getDItem(AlterDialog, 3, itemType, item, Box);
  295.         TempString := copy(Str1, 31, 5);
  296.         Strip(TempString);
  297.         StringToNum(TempString, OldLevel);
  298.         SetIText(Handle(item), TempString);
  299.  
  300.         getDItem(AlterDialog, 4, itemType, item, Box);
  301.         TempString := copy(Str1, 36, 5);
  302.         Strip(TempString);
  303.         SetIText(Handle(item), TempString);
  304.  
  305.         getDItem(AlterDialog, 5, itemType, item, Box);
  306.         thisButton := ControlHandle(item);
  307.         if Str1[44] = 'Y' then
  308.             SetCtlValue(thisButton, 1)
  309.         else
  310.             SetCtlValue(thisButton, 0);
  311.  
  312.         getDItem(AlterDialog, 13, itemType, item, Box);
  313.         AlterTitle := copy(Str1, 6, 25);
  314.         Strip(AlterTitle);
  315.         for FormatCount := length(AlterTitle) downto 1 do
  316.             if AlterTitle[FormatCount] = '.' then
  317.                 AlterTitle := copy(AlterTitle, 1, length(AlterTitle) - 1)
  318.             else
  319.                 leave;
  320.         if length(AlterTitle) < 25 then
  321.             for FormatCount := 1 to (25 - length(AlterTitle)) do
  322.                 AlterTitle := concat(' ', AlterTitle);
  323.         SetIText(Handle(item), AlterTitle);
  324.  
  325.         SelIText(AlterDialog, 3, 0, 32767);
  326.  
  327.     end;
  328.  
  329. {-----------------------------------------------------------------    }
  330.  
  331. procedure UpdateList (TheString: STR255);
  332.  
  333.     var
  334.         HowLong: integer;
  335.  
  336.     begin
  337.         HowLong := 255;
  338.         LSetSelect(true, TheCell, MessageList);        {turn it on}
  339.         LAutoScroll(MessageList);
  340.  
  341.         LGetCell(Pointer(Ord(@TheString) + 1), HowLong, theCell, MessageList);
  342.         TheString[0] := Chr(length(TheString));
  343.         FillDialogItems(TheString, OldLevel);
  344.     end;
  345.  
  346. {-----------------------------------------------------------------    }
  347.  
  348. procedure ChangeListEntry;
  349.  
  350.     var
  351.         Checker: longint;
  352.         StrLength, ListingCount, StringCount: integer;
  353.  
  354.     begin
  355.         getDItem(AlterDialog, 3, itemType, item, Box);
  356.         GetIText(Handle(item), LimitString);
  357.         StringToNum(LimitString, Checker);
  358.         if Checker > 9999 then
  359.             Checker := 0;
  360.         NumToString(Checker, LimitString);
  361.         while length(LimitString) < 5 do
  362.             LimitString := concat(' ', LimitString);
  363.         getDItem(AlterDialog, 4, itemType, item, Box);
  364.         GetIText(Handle(item), AgeString);
  365.         StringToNum(AgeString, Checker);
  366.         if Checker > 9999 then
  367.             Checker := 0;
  368.         NumToString(Checker, AgeString);
  369.         while length(AgeString) < 5 do
  370.             AgeString := concat(' ', AgeString);
  371.         getDItem(AlterDialog, 5, itemType, item, Box);
  372.         if GetCtlValue(ControlHandle(item)) = 1 then
  373.             BackUpString := 'Y'
  374.         else
  375.             BackUpString := 'N';
  376.         StrLength := 255;
  377.         LGetCell(@TempString, StrLength, theCell, MessageList);
  378.         SettingString[0] := Chr(StrLength);
  379.         for StringCount := 1 to StrLength do
  380.             SettingString[StringCount] := TempString[StringCount - 1];
  381.         for ListingCount := 1 to 5 do
  382.             SettingString[30 + ListingCount] := LimitString[ListingCount];
  383.         for ListingCount := 1 to 5 do
  384.             SettingString[35 + ListingCount] := AgeString[ListingCount];
  385.         SettingString[44] := BackUpString;
  386.         LSetCell(Pointer(ord(@SettingString) + 1), Length(SettingString), theCell, MessageList);
  387.     end;
  388.  
  389. {-----------------------------------------------------------------    }
  390.  
  391. procedure ButtonFlicker (TheButton: integer);
  392.  
  393.     var
  394.         TempLongInt: longint;
  395.  
  396.     begin
  397.         getDItem(AlterDialog, TheButton, itemType, item, Box);
  398.         HiLiteControl(ControlHandle(item), 1);
  399.         Delay(5, TempLongInt);
  400.         HiLiteControl(ControlHandle(item), 0);
  401.     end;
  402.  
  403. {-----------------------------------------------------------------    }
  404.  
  405. function CommandFilter (theDialog: DialogPtr; var theEvent: EventRecord; var ItemHit: integer): boolean;
  406.  
  407.     var
  408.         keyPressed: integer;
  409.  
  410.     begin
  411.         CommandFilter := false;
  412.         if BitAnd(TheEvent.what, keyDown) = keyDown then
  413.             begin
  414.                 if BitAnd(theEvent.modifiers, cmdKey) = cmdKey then
  415.                     begin
  416.                         keyPressed := BROTR(BitAnd(theEvent.Message, keyCodeMask), 8);
  417.                         case keyPressed of
  418.  
  419.                             1:              {    Save    }
  420.                                 begin
  421.                                     ItemHit := 1;
  422.                                     ButtonFlicker(1);
  423.                                 end;
  424.  
  425.                             8:             {    Cancel    }
  426.                                 begin
  427.                                     ItemHit := 2;
  428.                                     ButtonFlicker(2);
  429.                                 end;
  430.  
  431.                             11:             {    Backup    }
  432.                                 begin
  433.                                     ItemHit := 5;
  434.                                     ButtonFlicker(5);
  435.                                 end;
  436.  
  437.                             3: 
  438.                                 begin
  439.                                     ItemHit := 6;    {    First    }
  440.                                     ButtonFlicker(6);
  441.                                 end;
  442.                             37: 
  443.                                 begin
  444.                                     ItemHit := 7;    {    Last        }
  445.                                     ButtonFlicker(7);
  446.                                 end;
  447.  
  448.                             35: 
  449.                                 begin
  450.                                     ItemHit := 8;    {    Previous    }
  451.                                     ButtonFlicker(8);
  452.                                 end;
  453.  
  454.                             45: 
  455.                                 begin
  456.                                     ItemHit := 9;    {    Next        }
  457.                                     ButtonFlicker(9);
  458.                                 end;
  459.  
  460.                             4: 
  461.                                 begin
  462.                                     ItemHit := 10;     {    Help        }
  463.                                     ButtonFlicker(10);
  464.                                 end;
  465.  
  466.                             otherwise
  467.                                 ;
  468.  
  469.                         end;    {    Case statement    }
  470.                         CommandFilter := true;
  471.                     end        {    if Command key down    }
  472.                 else
  473.                     begin
  474.                         keyPressed := BROTR(BitAnd(theEvent.Message, keyCodeMask), 8);
  475.                         case keyPressed of
  476.  
  477.                             52, 76, 36: 
  478.                                 begin
  479.                                     ItemHit := 1;    {    Enter, extended Enter, Return    }
  480.                                     CommandFilter := true;
  481.                                     ButtonFlicker(1);
  482.                                 end;
  483.  
  484.                             otherwise
  485.                                 ;
  486.  
  487.                         end;    {    Case statement    }
  488.                     end;
  489.             end;    {    if key down    }
  490.     end;
  491.  
  492. {-----------------------------------------------------------------    }
  493.  
  494. procedure SelectionMade;
  495.  
  496.     var
  497.         StrLength, code, Counter, AlterCount: Integer;
  498.         thisCell, nextCell, AlterDone: Boolean;
  499.         where: point;
  500.         port: WindowPtr;
  501.         TempLongint: longint;
  502.         theRgn: RgnHandle;
  503.  
  504.     begin
  505.         InitCursor;
  506.         theCell.h := 0;
  507.         theCell.v := 0;
  508.         for nextCell := false to true do
  509.             begin
  510.                 thisCell := LGetSelect(nextCell, theCell, MessageList);
  511.                 if thisCell then
  512.                     begin
  513.                         StrLength := 255;
  514.                         LGetCell(Pointer(Ord(@SettingString) + 1), StrLength, theCell, MessageList);
  515.                         SettingString[0] := Chr(StrLength);
  516.  
  517.                         AlterDone := false;
  518.                         AlterDialog := GetNewDialog(AlterSecsID, nil, Pointer(-1));
  519.                         SetPort(AlterDialog);
  520.                         FrameDItem(AlterDialog, Ok);
  521.  
  522.                         FillDialogItems(SettingString, OldLevel);
  523.  
  524.                         if StillDown then
  525.                             repeat
  526.                             until not Button;
  527.  
  528.                         FlushEvents(EveryEvent, 0);
  529.  
  530.                         repeat
  531.                             ModalDialog(@CommandFilter, ItemHit);
  532.  
  533.                             case ItemHit of
  534.                                 1: {     Save button hit        }
  535.                                     begin
  536.                                         ChangeListEntry;
  537.                                         Changed := true;
  538.                                         AlterDone := true;
  539.                                     end;
  540.                                 2: {     Cancel button hit        }
  541.                                     AlterDone := true;
  542.  
  543.                                 5: {     B/U toggle hit        }
  544.                                     begin
  545.                                         getDItem(AlterDialog, 5, itemType, item, Box);
  546.                                         if GetCtlValue(ControlHandle(item)) = 0 then
  547.                                             SetCtlValue(ControlHandle(item), 1)
  548.                                         else
  549.                                             SetCtlValue(ControlHandle(item), 0);
  550.                                     end;
  551.  
  552.                                 6: {     First button hit        }
  553.                                     begin
  554.                                         ChangeListEntry;
  555.                                         Changed := true;
  556.                                         LSetSelect(false, TheCell, MessageList);    {turn it off}
  557.                                         theCell.v := 0;
  558.                                         UpdateList(SettingString);
  559.                                     end;
  560.  
  561.                                 7: {     Last Button hit        }
  562.                                     begin
  563.                                         ChangeListEntry;
  564.                                         Changed := true;
  565.                                         LSetSelect(false, TheCell, MessageList);    {turn it off}
  566.                                         theCell.v := SectionCount - 1;
  567.                                         UpdateList(SettingString);
  568.                                     end;
  569.  
  570.                                 8: {     Previous button hit        }
  571.                                     begin
  572.                                         ChangeListEntry;
  573.                                         Changed := true;
  574.                                         LSetSelect(false, TheCell, MessageList);    {turn it off}
  575.                                         if theCell.v = 0 then
  576.                                             theCell.v := SectionCount - 1
  577.                                         else
  578.                                             theCell.v := pred(theCell.v);
  579.                                         UpdateList(SettingString);
  580.                                     end;
  581.  
  582.                                 9: {     Next button hit        }
  583.                                     begin
  584.                                         ChangeListEntry;
  585.                                         Changed := true;
  586.                                         LSetSelect(false, TheCell, MessageList);    {turn it off}
  587.                                         if theCell.v < SectionCount - 1 then
  588.                                             theCell.v := succ(theCell.v)
  589.                                         else
  590.                                             theCell.v := 0;
  591.                                         UpdateList(SettingString);
  592.                                     end;
  593.  
  594.                                 10: {     Help button hit        }
  595.                                     begin
  596.                                         GetHelp(257);
  597.                                         BeginUpdate(OptionWindow);
  598.                                         Refresh;
  599.                                         theRgn := WindowPtr(OptionWindow)^.VisRgn;
  600.                                         LUpdate(theRgn, MessageList);
  601.                                         EndUpdate(OptionWindow);
  602.                                         SetPort(AlterDialog);
  603.                                         FrameDItem(AlterDialog, Ok);
  604.                                     end;
  605.  
  606.                                 otherwise
  607.                                     ;
  608.  
  609.                             end;        {    case ItemHit    }
  610.                         until AlterDone;
  611.                         DisposDialog(AlterDialog);
  612.                         theCell.h := 0;
  613.                         theCell.v := 0;
  614.                         Leave;        {    exit the for loop since we're done    }
  615.                     end;        {    if thisCell    }
  616.             end;        {    for nextCell := false to true    }
  617.  
  618. {    update counter    }
  619.  
  620.         TotalLimits := 0;
  621.         theCell.h := 0;
  622.         for Counter := 1 to SectionCount do
  623.             begin
  624.                 theCell.v := Counter - 1;
  625.                 LGetCell(@SettingString, StrLength, theCell, MessageList);
  626.                 SettingString[0] := chr(StrLength);
  627.                 TempString := copy(SettingString, 30, 5);
  628.                 while TempString[1] = ' ' do
  629.                     TempString := copy(TempString, 2, length(TempString) - 1);
  630.                 StringToNum(TempString, TempLongint);
  631.                 if TempLongint > 0 then
  632.                     TotalLimits := TotalLimits + TempLongint;
  633.             end;
  634.  
  635.         SetPort(OptionWindow);
  636.         ForeColor(RedColor);
  637.         GetDItem(OptionWindow, 1, ItemType, Item, Box);
  638.         NumToString(SectionCount, TempString);
  639.         SetIText(Item, TempString);
  640.  
  641.         GetDItem(OptionWindow, 2, ItemType, Item, Box);
  642.         NumToString(TotalLimits, TempString);
  643.         SetIText(Item, TempString);
  644.  
  645.         GetDItem(OptionWindow, 4, ItemType, Item, Box);
  646.         NumToString(TotalLimits div SectionCount, TempString);
  647.         SetIText(Item, TempString);
  648.         ForeColor(BlackColor);
  649.  
  650.     end;
  651.  
  652. {-----------------------------------------------------------------    }
  653.  
  654. procedure ShowBigHelp;
  655.  
  656.     var
  657.         HelpItem: integer;
  658.  
  659.     begin
  660.         InitCursor;
  661.         HelpDialog := GetNewDialog(1010, nil, Pointer(-1));
  662.         SetPort(HelpDialog);
  663.         FrameDItem(HelpDialog, Ok);
  664.         if StillDown then
  665.             repeat
  666.             until not Button;
  667.  
  668.         repeat
  669.             ModalDialog(nil, HelpItem);
  670.         until (HelpItem = 1);
  671.  
  672.         DisposDialog(HelpDialog);
  673.     end;
  674.  
  675. {-----------------------------------------------------------------    }
  676.  
  677. procedure FillNumbers (GlobalString: STR255; Offset: integer);
  678.  
  679. {    Fills section data in list with numeric data for Limit and Age field.    }
  680. {    Offset determines where data is written—29 for Limit, 34 for Age.    }
  681.  
  682.     var
  683.         Counter, InsertCount, TheLength: integer;
  684.         ListLine: STR255;
  685.         GlobalNumber: longint;
  686.  
  687.     begin
  688.         StringToNum(GlobalString, GlobalNumber);        {    Make sure this is a    }
  689.         if GlobalNumber > 9999 then                {    valid number.        }
  690.             GlobalNumber := 0;
  691.  
  692.         if Offset = 29 then    {    Adjust cumulative Limit figure    }
  693.             begin
  694.                 if GlobalNumber > 0 then
  695.                     TotalLimits := GlobalNumber * SectionCount
  696.                 else
  697.                     TotalLimits := 0;
  698.                 SetPort(OptionWindow);
  699.                 ForeColor(RedColor);
  700.                 GetDItem(OptionWindow, 1, ItemType, Item, Box);
  701.                 NumToString(SectionCount, TempString);
  702.                 SetIText(Item, TempString);
  703.  
  704.                 GetDItem(OptionWindow, 2, ItemType, Item, Box);
  705.                 NumToString(TotalLimits, TempString);
  706.                 SetIText(Item, TempString);
  707.  
  708.                 GetDItem(OptionWindow, 4, ItemType, Item, Box);
  709.                 NumToString(TotalLimits div SectionCount, TempString);
  710.                 SetIText(Item, TempString);
  711.             end;
  712.         NumToString(GlobalNumber, GlobalString);
  713.         while length(GlobalString) < 5 do            {    Pad to length 5    }
  714.             GlobalString := concat(' ', GlobalString);
  715.         inCell.h := 0;
  716.         for Counter := 1 to SectionCount do
  717.             begin
  718.                 inCell.v := Counter - 1;
  719.                 TheLength := 255;
  720.                 LGetCell(@ListLine, TheLength, inCell, MessageList);
  721.                 for InsertCount := 1 to 5 do
  722.                     ListLine[Offset + InsertCount] := GlobalString[InsertCount];
  723.                 LSetCell(@ListLine, TheLength, inCell, MessageList);
  724.             end;
  725.     end;
  726.  
  727. {-----------------------------------------------------------------    }
  728.  
  729. procedure FillBackup (GlobalString: STR255);
  730.  
  731.     var
  732.         Counter, TheLength: integer;
  733.         ListLine: STR255;
  734.  
  735.     begin
  736.         GlobalString := copy(GlobalString, 1, 1);
  737.         uprString(GlobalString, false);
  738.         inCell.h := 0;
  739.         for Counter := 1 to SectionCount do
  740.             begin
  741.                 inCell.v := Counter - 1;
  742.                 TheLength := 255;
  743.                 LGetCell(@ListLine, TheLength, inCell, MessageList);
  744.                 if GlobalString = 'Y' then
  745.                     begin
  746.                         ListLine[43] := 'Y';
  747.                         LSetCell(@ListLine, TheLength, inCell, MessageList);
  748.                     end
  749.                 else
  750.                     begin
  751.                         ListLine[43] := 'N';
  752.                         LSetCell(@ListLine, TheLength, inCell, MessageList);
  753.                     end;
  754.             end;
  755.     end;
  756.  
  757. {-----------------------------------------------------------------    }
  758.  
  759. procedure RotateDog (var DogCount: integer);
  760.  
  761.     begin
  762.         SetCursor(GetCursor(1000 + DogCount)^^);
  763.         if DogCount < 8 then
  764.             DogCount := succ(DogCount)
  765.         else
  766.             DogCount := 1;
  767.     end;
  768.  
  769. {-----------------------------------------------------------------    }
  770.  
  771. function FindPrefsFile: integer;
  772.  
  773.     var
  774.         theWorld: SysEnvRec;
  775.         sysVRef, prefsRef: integer;
  776.         SystemPath: str255;
  777.         fndrInfo: FInfo;
  778.  
  779.     begin
  780.         newExternalFile := false;
  781.         prefsRef := 0;
  782.         err := SysEnvirons(1, theWorld);
  783.         if err = noErr then
  784.             begin
  785.                 sysVRef := theWorld.sysVRefNum;    {it's in the System Folder}
  786.                 MakePath('System', sysVRef, SystemPath);
  787.                 prefsRef := OpenResFile(concat(SystemPath, 'Preferences:mehit prefs'));
  788.                 if (PrefsRef = -1) then
  789.                     begin
  790.                         CreateResFile(concat(SystemPath, 'Preferences:mehit prefs'));
  791.                         if ResError = noErr then
  792.                             begin
  793.                                 newExternalFile := true;
  794.                                 err := GetFInfo(concat(SystemPath, 'Preferences:mehit prefs'), sysVRef, fndrInfo);
  795.                                 with fndrInfo do
  796.                                     begin
  797.                                         fdType := 'pref';
  798.                                         fdCreator := 'mhtb';
  799.                                     end;
  800.                                 err := SetFInfo(concat(SystemPath, 'Preferences:mehit prefs'), sysVRef, fndrInfo);
  801.                                 prefsRef := OpenResFile(concat(SystemPath, 'Preferences:mehit prefs'));
  802.                             end
  803.                         else
  804.                             begin
  805.                                 prefsRef := OpenResFile(concat(SystemPath, 'mehit prefs'));
  806.                                 if (PrefsRef = -1) then
  807.                                     begin
  808.                                         newExternalFile := true;
  809.                                         CreateResFile(concat(SystemPath, 'mehit prefs'));
  810.                                     end;
  811.                                 err := GetFInfo(concat(SystemPath, 'mehit prefs'), sysVRef, fndrInfo);
  812.                                 with fndrInfo do
  813.                                     begin
  814.                                         fdType := 'pref';
  815.                                         fdCreator := 'mhtb';
  816.                                     end;
  817.                                 err := SetFInfo(concat(SystemPath, 'mehit prefs'), sysVRef, fndrInfo);
  818.                                 prefsRef := OpenResFile(concat(SystemPath, 'mehit prefs'));
  819.                             end;
  820.                     end;
  821.             end;
  822.         FindPrefsFile := prefsRef
  823.     end;
  824.  
  825. {-----------------------------------------------------------------    }
  826.  
  827. procedure UpdateResources;
  828.  
  829.     var
  830.         ResourceCount, TheLength, BuildCount, STR_Number, DogCount: integer;
  831.         AHandle: Handle;
  832.         Description, ListLine, STR_NAME: STR255;
  833.  
  834.     begin
  835.         SetCursor(GetCursor(1001)^^);
  836.         DogCount := 2;
  837.         UseResFile(externalResFile);
  838.         for ResourceCount := 1 to 255 do
  839.             begin
  840.                 AHandle := GetResource('STR ', 1000 + ResourceCount);
  841.                 if AHandle^ <> nil then
  842.                     RmveResource(AHandle);
  843.                 if ResourceCount mod 68 = 0 then
  844.                     RotateDog(DogCount);
  845.             end;
  846.         UpdateResFile(externalResFile);
  847.         inCell.h := 0;
  848.         for ResourceCount := 1 to SectionCount do
  849.             begin
  850.                 Description := '';
  851.                 TempString := '';
  852.                 inCell.v := ResourceCount - 1;
  853.                 TheLength := 255;
  854.                 LGetCell(@ListLine, TheLength, inCell, MessageList);
  855.                 ListLine[0] := chr(TheLength);
  856.                 for BuildCount := 30 to 34 do
  857.                     Description := concat(Description, ListLine[BuildCount]);
  858.                 Strip(Description);
  859.                 Description := concat(Description, '&');
  860.                 for BuildCount := 35 to 39 do
  861.                     TempString := concat(TempString, ListLine[BuildCount]);
  862.                 Strip(TempString);
  863.                 Description := concat(Description, TempString, '&&', ListLine[43]);
  864.                 NumToString(Sections[ResourceCount]^^.Number, STR_Name);
  865.                 STR_Name := concat('Section ', STR_Name);
  866.                 STR_Number := 1000 + Sections[ResourceCount]^^.Number;
  867.                 AddResource(Handle(NewString(Description)), 'STR ', STR_Number, STR_Name);
  868.                 UpdateResFile(externalResFile);
  869.                 RotateDog(DogCount)
  870.             end;
  871.         SetCursor(GetCursor(1000)^^);
  872.     end;
  873.  
  874. {-----------------------------------------------------------------    }
  875.  
  876. procedure SavingResources;
  877.     var
  878.         theDialog: DialogPtr;
  879.  
  880.     begin
  881.         theDialog := GetNewDialog(1006, nil, Pointer(-1));
  882.         SetPort(theDialog);
  883.         DrawDialog(theDialog);
  884.         UpdateResources;
  885.         DisposDialog(theDialog);
  886.         Refresh;
  887.     end;
  888.  
  889. {-----------------------------------------------------------------    }
  890.  
  891. procedure AskSaveChanges;
  892.  
  893.     var
  894.         theRgn: RgnHandle;
  895.         theDialog: DialogPtr;
  896.  
  897.     begin
  898.         theDialog := GetNewDialog(SaveChangesID, nil, Pointer(-1));
  899.         SetPort(theDialog);
  900.         FrameDItem(theDialog, Ok);
  901.         ModalDialog(nil, AboutItem);
  902.         repeat
  903.         until (AboutItem = 1) | (AboutItem = 2);
  904.         DisposDialog(theDialog);
  905.         if AboutItem = 1 then
  906.             SavingResources;
  907.         Changed := false;
  908.         Refresh;
  909.         theRgn := WindowPtr(OptionWindow)^.VisRgn;
  910.         LUpdate(theRgn, MessageList);
  911.     end;
  912.  
  913. {-----------------------------------------------------------------    }
  914.  
  915. procedure HandleMenu (theMenu, theItem: integer);
  916.  
  917.     var
  918.         theDialog: DialogPtr;
  919.         theName, GlobalString, ListLine: Str255;
  920.         Counter, ListRef, TheLength: integer;
  921.         ListXfer, AFilePos: longint;
  922.         where: point;
  923.         ListCell: Cell;
  924.         whatToFind: SFTypeList;
  925.         fileReply: SFReply;
  926.  
  927.     begin
  928.         case theMenu of
  929.             AppleID: {    Apple Menu    }
  930.                 case theItem of
  931.                     1: 
  932.                         begin
  933.                             theDialog := GetNewDialog(AboutID, nil, Pointer(-1));
  934.                             setport(theDialog);
  935.                             CenterDLOG(theDialog);
  936.                             ForeColor(RedColor);
  937.                             TextFont(Monaco);
  938.                             TextSize(9);
  939.                             GetDItem(theDialog, 3, ItemType, Item, Box);
  940.                             SetIText(Item, mehitVersion);
  941.                             ShowWindow(theDialog);
  942.                             SetCursor(GetCursor(1000)^^);
  943.                             ModalDialog(nil, AboutItem);
  944.                             repeat
  945.                             until AboutItem = 1;
  946.                             DisposDialog(theDialog);
  947.                             Refresh;
  948.                             InitCursor;
  949.                         end; {case 1}
  950.  
  951.                     otherwise
  952.                         begin
  953.                             GetItem(AppleMenu, theItem, TheName);
  954.                             theItem := OpenDeskAcc(TheName);
  955.                         end; {otherwise}
  956.                 end; {    case 256    }
  957.  
  958.             FileID:     {    File Menu    }
  959.                 case theItem of
  960.                     1:                 {    Configure        }
  961.                         begin
  962.                             InitCursor;
  963.                             HideWindow(OptionWindow);
  964.                             ConfigureDialog;
  965.                             ShowWindow(OptionWindow);
  966.                             Refresh;
  967.                         end;
  968.                     2:                 {    Run            }
  969.                         begin
  970.                             if (Changed = true) then
  971.                                 AskSaveChanges;
  972.                             DisposDialog(OptionWindow);
  973.                             WindowGone := true;
  974.                             ReadSTRs;
  975.                             BackupMessages;
  976.                             Done := true;
  977.                         end;
  978.                     4:                 {    Save            }
  979.                         begin
  980.                             SavingResources;
  981.                             Changed := false;
  982.                         end;
  983.                     5:                 {    Revert        }
  984.                         begin
  985.                             FillList;
  986.                             Changed := false;
  987.                         end;
  988.                     7:                 {    Save List as Text        }
  989.                         begin
  990.                             where.h := 60;
  991.                             where.v := 80;
  992.                             SFPPutFile(where, 'save listing as…', 'msg section list', nil, fileReply, 3998, nil);
  993.  
  994.                             if fileReply.good then
  995.                                 begin
  996.                                     TimeAt;
  997.                                     Err := FSDelete(fileReply.fname, fileReply.vRefNum);
  998.                                     Err := Create(fileReply.fname, fileReply.vRefNum, DefaultsPtr^.TextType, 'TEXT');
  999.                                     Err := FSOpen(fileReply.fname, fileReply.vRefNum, ListRef);
  1000.                                     Err := WrLn(ListRef, concat('  bbs message sections ', DateString, ENDLINE));
  1001.                                     Err := WrLn(ListRef, 'no.  title                     limit age  b/u');
  1002.                                     Err := WrLn(ListRef, '---------------------------------------------');
  1003.                                     ListCell.h := 0;
  1004.                                     for Counter := 1 to SectionCount do
  1005.                                         begin
  1006.                                             ListCell.v := Counter - 1;
  1007.                                             TheLength := 255;
  1008.                                             LGetCell(Pointer(ord(@ListLine) + 1), TheLength, ListCell, MessageList);
  1009.                                             ListLine[0] := chr(TheLength);
  1010.                                             Err := WrLn(ListRef, ListLine);
  1011.                                         end;        {    for Counter := 1 to SectionCount    }
  1012.                                     Err := FSClose(ListRef);
  1013.                                 end;    {    if fileReply.good    }
  1014.                         end;
  1015.                     9:                 {    Transfer        }
  1016.                         begin
  1017.                             if Changed = true then
  1018.                                 AskSaveChanges;
  1019.                             SFwhere.h := 60;
  1020.                             SFwhere.v := 80;
  1021.                             whatToFind[0] := 'APPL';
  1022.                             ParamText('select application to launch', '', '', '');
  1023.                             SFPGetFile(SFwhere, '', nil, 1, whatToFind, nil, fileReply, 4000, nil);
  1024.                             if fileReply.good then
  1025.                                 begin
  1026.                                     for Counter := 1 to SectionCount do
  1027.                                         if Handle(Sections[Counter])^ <> nil then
  1028.                                             begin
  1029.                                                 HUnlock(Handle(Sections[Counter]));
  1030.                                                 DisposHandle(Handle(Sections[Counter]));
  1031.                                             end;
  1032.                                     if DefaultsPtr <> nil then
  1033.                                         DisposPtr(POINTER(DefaultsPtr));
  1034.                                     if not WindowGone then
  1035.                                         DisposDialog(OptionWindow);
  1036.                                     TheLaunch := fileReply.fName;
  1037.                                     launchVRefNum := fileReply.vRefNum;
  1038.                                     Err := SetVol(nil, launchVRefNum);
  1039.                                     Transfer;
  1040.                                 end;
  1041.                         end;
  1042.  
  1043.                     10:                 {    Quit            }
  1044.                         begin
  1045.                             if Changed = true then
  1046.                                 AskSaveChanges;
  1047.                             if DefaultsPtr <> nil then
  1048.                                 DefaultsPtr^.DNextLaunch := '';
  1049.                             Done := true;
  1050.                         end;
  1051.                     otherwise
  1052.                         ;
  1053.                 end; {    case 257    }
  1054.  
  1055.             EditID:             {    Edit Menu    }
  1056.                 TrueFalse := SystemEdit(theItem - 1);    {    Feeds DAs correctly    }
  1057.  
  1058.             GlobalID:        {    Global Menu    }
  1059.                 case theItem of
  1060.                     1:                     {    Limit    }
  1061.                         begin
  1062.                             ParamText('limit', '', '', '');
  1063.                             GlobalDialog(GlobalString);
  1064.                             if GlobalString <> '' then
  1065.                                 FillNumbers(GlobalString, 29);
  1066.                             Refresh;
  1067.                         end;
  1068.  
  1069.                     2:                      {    Age        }
  1070.                         begin
  1071.                             ParamText('age', '', '', '');
  1072.                             GlobalDialog(GlobalString);
  1073.                             if GlobalString <> '' then
  1074.                                 FillNumbers(GlobalString, 34);
  1075.                         end;
  1076.  
  1077.                     3:                      {    Backup    }
  1078.                         begin
  1079.                             ParamText('backup status', '', '', '');
  1080.                             GlobalDialog(GlobalString);
  1081.                             if GlobalString <> '' then
  1082.                                 FillBackup(GlobalString);
  1083.                         end;
  1084.  
  1085.                     5:      {    Help    }
  1086.                         begin
  1087.                             GetHelp(256);
  1088.                             Refresh;
  1089.                         end;
  1090.  
  1091.                 end;    {    case theItem    }
  1092.  
  1093.         end;    {    case theMenu    }
  1094.  
  1095.         HiliteMenu(0);
  1096.     end;
  1097.  
  1098. {-----------------------------------------------------------------    }
  1099.  
  1100. procedure HandleEvent (TheEvent: EventRecord);
  1101.  
  1102.     var
  1103.         where: point;
  1104.         code, Counter, TheLength, BuildCount, Result: integer;
  1105.         tempport: GrafPtr;
  1106.         port: WindowPtr;
  1107.         theInfo: longint;
  1108.         theItem, theMenu, ResourceCount: integer;
  1109.         theDialog: DialogPtr;
  1110.         theBool, Bool2: Boolean;
  1111.         theRgn: RgnHandle;
  1112.         GlobalString: STR255;
  1113.         TempBox: rect;
  1114.         AKeyMap: KeyMap;
  1115.  
  1116.     begin
  1117.         case TheEvent.what of
  1118.             MouseDown: 
  1119.                 begin
  1120.                     where := TheEvent.where;
  1121.                     code := FindWindow(where, port);
  1122.                     case Code of
  1123.                         inMenuBar: 
  1124.                             begin
  1125.                                 theInfo := MenuSelect(where);
  1126.                                 theMenu := HiWord(theInfo);
  1127.                                 theItem := LoWord(theInfo);
  1128.                                 HandleMenu(theMenu, theItem);
  1129.                             end; {case MenuBar}
  1130.                         inContent: 
  1131.                             begin
  1132.                                 if Port <> FrontWindow then
  1133.                                     SelectWindow(Port)
  1134.                                 else
  1135.                                     begin
  1136.                                         theBool := False;
  1137.                                         GlobalToLocal(where);
  1138.                                         if PtInRect(where, ScrollSect) then
  1139.                                             if LClick(where, TheEvent.Modifiers, MessageList) then
  1140.                                                 SelectionMade;
  1141.                                         if PtInRect(where, DClickBox) then
  1142.                                             begin
  1143.                                                 GetDItem(OptionWindow, 7, ItemType, Item, DClickBox);
  1144.                                                 EraseRect(DClickBox);
  1145.                                                 TextFont(0);
  1146.                                                 TextSize(12);
  1147.                                                 ForeColor(RedColor);
  1148.                                                 TempBox := DClickBox;
  1149.                                                 TempBox.top := TempBox.top + 5;
  1150.                                                 TempBox.bottom := TempBox.bottom + 5;
  1151.                                                 TempString := 'not here! try a bit lower…';
  1152.                                                 TextBox(Pointer(ord(@TempString) + 1), length(TempString), TempBox, teJustCenter);
  1153.                                                 TextFont(Monaco);
  1154.                                                 TextSize(9);
  1155.                                                 repeat
  1156.                                                 until not Button;
  1157.                                                 SetDItem(OptionWindow, 7, ItemType, Item, DClickBox);
  1158.                                                 DrawDialog(OptionWindow);
  1159.                                             end
  1160.                                         else if PtInRect(where, CatBox) then
  1161.                                             if BitAnd(theEvent.modifiers, optionKey) = optionKey then
  1162.                                                 begin
  1163.                                                     GetDItem(OptionWindow, 10, ItemType, Item, CatBox);
  1164.                                                     EraseRect(CatBox);
  1165.                                                     TextFont(Geneva);
  1166.                                                     TextSize(9);
  1167.                                                     ForeColor(BlueColor);
  1168.                                                     TempBox := CatBox;
  1169.                                                     TempBox.top := TempBox.top + 30;
  1170.                                                     TempBox.bottom := TempBox.bottom + 30;
  1171.                                                     TempBox.left := TempBox.left - 5;
  1172.                                                     TempBox.right := TempBox.right - 5;
  1173.                                                     TempString := concat('the honey bee is sad and cross', ENDLINE, 'and wicked as a weasel', ENDLINE);
  1174.                                                     TempString := concat(TempString, 'and when she perches on you boss', ENDLINE, 'she leaves a little measle', ENDLINE);
  1175.                                                     TextBox(Pointer(ord(@TempString) + 1), length(TempString), TempBox, teJustCenter);
  1176.                                                     TextFont(Monaco);
  1177.                                                     TextSize(9);
  1178.                                                     ForeColor(RedColor);
  1179.                                                     repeat
  1180.                                                     until not Button;
  1181.                                                     SetDItem(OptionWindow, 10, ItemType, Item, CatBox);
  1182.                                                     DrawDialog(OptionWindow);
  1183.                                                 end;
  1184.                                         ControlResult := FindControl(where, OptionWindow, WhichControl);
  1185.                                         if ControlResult = inButton then
  1186.                                             ControlResult := TrackControl(WhichControl, where, nil);
  1187.                                         if ControlResult <> 0 then
  1188.                                             if IsDialogEvent(TheEvent) then
  1189.                                                 if DialogSelect(TheEvent, theDialog, theItem) then
  1190.                                     end;
  1191.                             end; {Case inContent}
  1192.                         inGoAway: 
  1193.                             if TrackGoAway(port, where) then
  1194.                                 begin
  1195.                                     if Changed = true then
  1196.                                         AskSaveChanges;
  1197.                                     if DefaultsPtr <> nil then
  1198.                                         DefaultsPtr^.DNextLaunch := '';
  1199.                                     Done := true;
  1200.                                 end;
  1201.                         inDrag: 
  1202.                             DragWindow(port, where, ScreenBits.bounds);
  1203.                         inSysWindow: 
  1204.                             SystemClick(theEvent, port);
  1205.                     end; {Case Code}
  1206.                 end; {Case Mousedown}
  1207.             UpdateEvt: 
  1208.                 begin
  1209.                     BeginUpdate(OptionWindow);
  1210.                     Refresh;
  1211.                     theRgn := WindowPtr(OptionWindow)^.VisRgn;
  1212.                     LUpdate(theRgn, MessageList);
  1213.                     EndUpdate(OptionWindow);
  1214.                 end; {Case UpdateEvt}
  1215.  
  1216.             keyDown: 
  1217.                 begin
  1218.                     CharCode := BitAnd(TheEvent.message, CharCodeMask);
  1219.                     KeyCode := BROTR(BitAnd(TheEvent.message, KeyCodeMask), 8);    {    Bit rotate to right    }
  1220.                     if BitAnd(TheEvent.modifiers, cmdKey) = cmdKey then    {    Command key down    }
  1221.                         begin
  1222.                             theInfo := MenuKey(chr(CharCode));
  1223.                             theMenu := HiWord(theInfo);
  1224.                             theItem := LoWord(theInfo);
  1225.                             HandleMenu(theMenu, theItem);
  1226.                         end;    {    if BitAnd(TheEvent.modifiers, cmdKey) = cmdKey    }
  1227.  
  1228.                 end;    {    Case keyDown    }
  1229.  
  1230.         end; {Case theEvent of…    }
  1231.     end; {HandleEvent}
  1232.  
  1233. {-----------------------------------------------------------------    }
  1234.  
  1235.     var
  1236.         tempRef: integer;
  1237.  
  1238. begin
  1239.     MaxApplZone;
  1240.     SetCursor(GetCursor(1000)^^);
  1241.     Err := HGetVol(@gVolName, vRefNum, dirID);        { Get volume ref # & dirID for default volume    }
  1242.     gDefaultpath := PathNameFromDirID(dirID, vRefNum);    { Get full pathname    }
  1243.     DefaultVol := vRefNum;
  1244.     internalResFile := CurResFile;
  1245.     externalResFile := findPrefsFile;
  1246.  
  1247.     ReadConfig;    {sets MultiFinder value}
  1248.     if MultiFinder then
  1249.         IgnoreBool := WaitNextEvent(EveryEvent, TabbyEventRec, sleep, nil);
  1250.     ReadMESSAGES;
  1251.     if MultiFinder then
  1252.         IgnoreBool := WaitNextEvent(EveryEvent, TabbyEventRec, sleep, nil);
  1253.  
  1254.     if Demo then
  1255.         Amnesia;
  1256.     ReadSTRs;
  1257.     NeedConfig := false;
  1258.     StuffItExists := false;
  1259.  
  1260.     with DefaultsPtr^ do
  1261.         begin
  1262.             Err := FSOpen(DNextLaunch, vRefNum, RefNum);
  1263.             if Err = NoErr then
  1264.                 Err := FSClose(RefNum)
  1265.             else
  1266.                 NeedConfig := true;
  1267.  
  1268.             TempString := concat(DBackupPath, 'junk');
  1269.             Err := Create(TempString, vRefNum, 'QED1', 'TEXT');
  1270.             if Err = NoErr then
  1271.                 Err := FSDelete(TempString, vRefNum)
  1272.             else
  1273.                 NeedConfig := true;
  1274.  
  1275.             TempString := concat(DefaultsPtr^.DTextPath, 'junk');
  1276.             Err := Create(TempString, vRefNum, 'QED1', 'TEXT');
  1277.             if Err = NoErr then
  1278.                 Err := FSDelete(TempString, vRefNum)
  1279.             else
  1280.                 NeedConfig := true;
  1281.  
  1282.             if newExternalFile then
  1283.                 NeedConfig := true;
  1284.         end;
  1285.  
  1286.     mehitVersion := ReadVersion;
  1287.     if Demo then
  1288.         mehitVersion := concat(mehitVersion, ' demo');
  1289.     FlushEvents(EveryEvent, 0);
  1290.  
  1291.     if (not Button) & (not NeedConfig) then
  1292.         BackupMessages
  1293.     else
  1294.         begin
  1295.             OptionWindow := GetNewDialog(1000, nil, Pointer(-1));
  1296.             SetPort(OptionWindow);
  1297.             GetDItem(OptionWindow, 7, ItemType, Item, DClickBox);
  1298.             GetDItem(OptionWindow, 10, ItemType, Item, CatBox);
  1299.  
  1300.             AppleMenu := GetMenu(AppleId);
  1301.             AddResMenu(AppleMenu, 'DRVR');    {    for those pesky DA's                }
  1302.             InsertMenu(AppleMenu, 0);
  1303.             FileMenu := GetMenu(FileId);
  1304.             InsertMenu(FileMenu, 0);
  1305.             EditMenu := GetMenu(EditId);
  1306.             InsertMenu(EditMenu, 0);
  1307.             GlobalMenu := GetMenu(GlobalId);
  1308.             InsertMenu(GlobalMenu, 0);
  1309.             DrawMenuBar;
  1310.  
  1311.             SetUpLists;
  1312.  
  1313.             done := False;            {    as we just started        }
  1314.             if not newExternalFile then
  1315.                 Changed := false            {    nothing changed yet        }
  1316.             else
  1317.                 Changed := true;            {no resource file found, so request a Save}
  1318.             beginning := true;
  1319.             WindowGone := false;
  1320.  
  1321.             repeat
  1322.                 if NeedConfig then
  1323.                     begin
  1324.                         ConfigureDialog;
  1325.                         Refresh;
  1326.                         NeedConfig := false
  1327.                     end;
  1328.                 if MultiFinder then
  1329.                     begin
  1330.                         if WaitNextEvent(EveryEvent, TheEvent, sleep, nil) then
  1331.                             HandleEvent(TheEvent)
  1332.                     end
  1333.                 else if GetNextEvent(EveryEvent, TheEvent) then
  1334.                     HandleEvent(TheEvent);
  1335.                 if beginning then
  1336.                     beginning := false;
  1337.  
  1338.                 if OptionWindow = FrontWindow then
  1339.                     begin
  1340.                         GetMouse(MouseLoc);
  1341.                         if PtInRect(MouseLoc, ScrollSect) | not (PtInRect(MouseLoc, OptionWindow^.portrect)) then
  1342.                             InitCursor
  1343.                         else
  1344.                             SetCursor(GetCursor(1000)^^);
  1345.                     end;
  1346.  
  1347.             until done = true;
  1348.  
  1349.             if not WindowGone then
  1350.                 DisposDialog(OptionWindow);
  1351.         end;        {else (not Button) & (not NeedConfig)}
  1352.  
  1353.     for Counter := 1 to SectionCount do
  1354.         if Handle(Sections[Counter])^ <> nil then
  1355.             begin
  1356.                 HUnlock(Handle(Sections[Counter]));
  1357.                 DisposHandle(Handle(Sections[Counter]));
  1358.             end;
  1359.  
  1360.     if DefaultsPtr <> nil then
  1361.         begin
  1362.             NextLaunch := DefaultsPtr^.DNextLaunch;
  1363.             DisposPtr(POINTER(DefaultsPtr));
  1364.         end;
  1365.  
  1366.     closeResFile(externalResFile);
  1367.  
  1368.     myCloseWD;
  1369.  
  1370.     if NextLaunch <> '' then
  1371.         LaunchNextAppl
  1372. end.